﻿using System;
using System.Runtime.InteropServices;
using HuaWeiCamera.Enums;
using HuaWeiCamera.Enums.SnapShot;
using HuaWeiCamera.Struct;

namespace HuaWeiCamera.Class
{
    /// <summary>
    /// 华为HoloSens SDC二次开发使用
    /// </summary>
    public static class HuaWeiSdkHelper
    {
        private const string SdkPath= "HWPuSDK.dll";
        #region 初始化和登录

        /// <summary>
        /// 初始化设备
        /// </summary>
        /// <param name="ulLinkMode">0自动 1手动 3混合模式</param>
        /// <param name="szLocalIp">本地IP</param>
        /// <param name="ulLocalPort">本地端口</param>
        /// <returns></returns>
        [DllImport(SdkPath, EntryPoint = "IVS_PU_Init", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool IVS_Pu_Init(uint ulLinkMode, string szLocalIp, uint ulLocalPort);
        /// <summary>
        /// 远程登录设备
        /// </summary>
        /// <param name="szLoginIp">设备IP</param>
        /// <param name="ulLoginPort">设备端口 6060</param>
        /// <param name="szUserName">登录名 ApiAdmin</param>
        /// <param name="szPasswd">登录密码 HuaWei123</param>
        /// <returns></returns>
        [DllImport(SdkPath, EntryPoint = "IVS_PU_Login", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
        public static extern uint IVS_PU_Login(string szLoginIp, uint ulLoginPort, string szUserName, string szPasswd);

        /// <summary>
        /// 初始化和登录设备
        /// </summary>
        /// <param name="sdcIp">SDC设备IP</param>
        /// <param name="sdcPort">SDC设备端口</param>
        /// <param name="sdcUser">SDC登录用户名</param>
        /// <param name="sdcPwd">SDC登录密码</param>
        /// <param name="errMsg">失败时的错误信息</param>
        /// <param name="ulIdentifyId">登录成功后返回登录句柄</param>
        public static void InitAndLogin(string sdcIp,uint sdcPort,string sdcUser,string sdcPwd,out uint ulIdentifyId,out string errMsg)
        {
            ulIdentifyId = 0;
            errMsg = "";
            //要开启TLS的情况时：初始化调用IVS_PU_InitEx接口，登录调用IVS_PU_Login 接口时端口号设置为6061
            if (!IVS_Pu_Init(1, "192.168.2.144", 6060))
            {
                errMsg=($"设备初始化失败，{GetLastErrorInfo()}");
                return;
            }

            //ulIdentifyId = IVS_PU_Login("192.168.2.250", 6060, "ApiAdmin", "HuaWei123");
            ulIdentifyId = IVS_PU_Login(sdcIp, sdcPort, sdcUser, sdcPwd);
            if (ulIdentifyId == 0)
            {
                errMsg=$"设备登录失败，{GetLastErrorInfo()}";
            }
        }

        #endregion

        #region 预览相关
        /// <summary>
        /// 实时预览
        /// </summary>
        /// <param name="ulIdentifyId">登录成功后返回的用户编号</param>
        /// <param name="pstRealPlayInfo">播放结构体</param>
        /// <param name="fRealDataCallBack">回调实现播放</param>
        /// <param name="pUsrData">传入码流数据 回调函数作为参数</param>
        /// <returns></returns>
        [DllImport(SdkPath, EntryPoint = "IVS_PU_RealPlay")]
        public static extern uint IVS_PU_RealPlay(uint ulIdentifyID, PU_REAL_PLAY_INFO_S[] pstRealPlayInfo, PfRealDataCallBack fRealDataCallBack, ref IntPtr pUsrData);

        public delegate void PfRealDataCallBack(IntPtr szBuffer, int lSize, IntPtr pUsrData);
        /// <summary>
        /// 停止实时预览
        /// </summary>
        /// <param name="ulIdentifyId">登录成功后返回的用户编号</param>
        /// <param name="ulRealHandle">实时播放句柄</param>
        /// <returns></returns>
        [DllImport(SdkPath, EntryPoint = "IVS_PU_StopRealPlay", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
        public static extern uint IVS_PU_StopRealPlay(uint ulIdentifyId, uint ulRealHandle);
        #endregion

        #region 人脸相关

        #region 人脸抓拍
        /// <summary>
        /// 元数据解析接口
        /// </summary>
        /// <param name="pFBuffer">数据缓存</param>
        /// <param name="ulFBLength">数据长度</param>
        /// <param name="eLayTwo">第二层元数据TYPE</param>
        /// <param name="pstMetaData">元数据结构</param>
        /// <returns></returns>
        [DllImport(SdkPath, EntryPoint = "IVS_User_GetMetaData")]
        public static extern bool IVS_User_GetMetaData(IntPtr pFBuffer, int ulFBLength, LAYER_TWO_TYPE eLayTwo, ref IntPtr pstMetaData);

        /// <summary>
        /// 释放元数据
        /// </summary>
        /// <param name="ppstMetaData">元数据结构</param>
        [DllImport(SdkPath, EntryPoint = "IVS_User_FreeMetaData", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
        public static extern void IVS_User_FreeMetaData(out IntPtr ppstMetaData);

        /// <summary>
        /// 开始抓拍
        /// </summary>
        /// <param name="ulIdentifyId">用户ID号</param>
        /// <param name="ulChannelId">通道号,一般为101</param>
        /// <param name="ulSnapCount">抓拍张数(1-10张)</param>
        /// <param name="ulSnapInterval">抓拍间隔(500~10000毫秒)</param>
        /// <param name="enSnapType">抓拍类型 </param>
        /// <returns>true代表成功，false代表失败，通过获取最后一次错误信息来看错误代码</returns>
        [DllImport(SdkPath, EntryPoint = "IVS_PU_StartSnapShot", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool IVS_PU_StartSnapShot(uint ulIdentifyId, uint ulChannelId, uint ulSnapCount, uint ulSnapInterval, PU_SNAPSHOT_TYPE enSnapType);

        #endregion


        #endregion

        #region 错误信息相关

        /// <summary>
        /// 获取最后一次错误代码
        /// </summary>
        /// <returns></returns>
        [DllImport(SdkPath, EntryPoint = "IVS_PU_GetLastError", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
        private static extern int IVS_PU_GetLastError();

        /// <summary>
        /// 根据错误代码返回错误信息
        /// </summary>
        /// <param name="ulErrorNo">错误编号</param>
        /// <returns></returns>
        [DllImport(SdkPath, EntryPoint = "IVS_PU_GetErrorMsg", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
        private static extern IntPtr IVS_PU_GetErrorMsg(int ulErrorNo);

        /// <summary>
        /// 返回最后一次错误码和错误信息
        /// </summary>
        /// <returns></returns>
        public static string GetLastErrorInfo()
        {
            var lastErrorCode = IVS_PU_GetLastError();
            var lastErrorMsg = Marshal.PtrToStringAnsi(IVS_PU_GetErrorMsg(lastErrorCode));

            return $"错误码：{IVS_PU_GetLastError()}，错误信息：{lastErrorMsg}";
        }

        #endregion
        
        #region 退出登录

        /// <summary>
        /// 退出登录
        /// </summary>
        /// <param name="ulIdentifyId">登录成功后返回的句柄编号</param>
        /// <returns></returns>
        [DllImport(SdkPath, EntryPoint = "IVS_PU_Logout", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool IVS_PU_Logout(uint ulIdentifyId);
        /// <summary>
        /// 反注册设备，退出时进行设备释放
        /// </summary>
        /// <returns></returns>
        [DllImport(SdkPath, EntryPoint = "IVS_PU_Cleanup", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool IVS_PU_Cleanup();

        #endregion

    }
}
